import { defineStore } from "pinia";
import type { RouteLocationNormalizedLoaded } from "vue-router";
import waiting from "@/utils/waiting";
import router from "@/router";
import { useMenuStore } from "./menu";

export type ViewTag = {
    name: string;
    title: string;
    fullPath: string;
    affix: boolean;
};

export enum TagsActions {
    /**
     * 刷新标签
     */
    REFRESH = "refresh",
    /**
     * 关闭标签
     */
    CLOSE = "close",
    /**
     * 关闭其他标签
     */
    CLOSE_OTHER = "other",
    /**
     * 关闭右侧标签
     */
    CLOSE_RIGHT = "right",
    /**
     * 全部关闭
     */
    CLOSE_ALL = "all",
}

type State = {
    viewVisible: boolean;
    current: ViewTag | null;
    viewTags: ViewTag[];
    aliveTags: string[];
};

export const useTagsStore = defineStore("tags", {
    state: (): State => ({
        viewVisible: true,
        current: null,
        viewTags: [],
        aliveTags: [],
    }),
    actions: {
        addViewTag(route: RouteLocationNormalizedLoaded) {
            if (this.viewTags.find((item) => item.name === route.name)) {
                return;
            }

            const menu = useMenuStore();
            console.log("store[tags] addViewTag", menu.routeNames, route.name);
            if (!menu.routeNames.includes(route.name as string)) return;

            const {
                meta: { affix, title },
                path,
                fullPath,
                name,
            } = route;

            const tag = { affix, title, fullPath: fullPath || path, name } as ViewTag;
            this.current = { ...tag };
            this.viewTags.push(tag);
            if (route.meta.keepAlive) this.aliveTags.push(route.name as string);
        },
        refreshView(tag: ViewTag) {
            this.aliveTags = this.aliveTags.filter((item) => item !== tag.name);
            this.viewVisible = false;

            setTimeout(() => {
                this.viewVisible = true;
                this.aliveTags.push(tag.name);
            }, 100);
        },
        async closeViewTag(tag: ViewTag) {
            if (tag.affix) {
                return;
            }

            const tagIndex = this.viewTags.findIndex((item) => item.name === tag.name);
            if (tagIndex === -1) return;
            this.viewTags.splice(tagIndex, 1);

            const aliveIndex = this.aliveTags.findIndex((item) => item === tag.name);
            if (aliveIndex > -1) {
                this.aliveTags.splice(aliveIndex, 1);
            }

            if (router.currentRoute.value.fullPath === tag.fullPath) {
                const nextTag = this.viewTags[tagIndex + 1] || this.viewTags[tagIndex - 1];
                const path = nextTag ? nextTag.fullPath : "/";

                await waiting(0);
                router.push(path);
            }
        },
        async batchClose(action: TagsActions, tag: ViewTag | null = null) {
            let routes: ViewTag[] = [];
            let path = action === TagsActions.CLOSE_ALL ? "/" : tag!.fullPath;

            switch (action) {
                case TagsActions.CLOSE_RIGHT:
                    {
                        const index = this.viewTags.findIndex((item) => item.name === tag!.name);
                        routes = this.viewTags.slice(index + 1).filter((item) => !item.affix);
                    }
                    break;
                case TagsActions.CLOSE_OTHER:
                    routes = this.viewTags.filter((item) => !item.affix && item.name !== tag!.name);
                    break;
                case TagsActions.CLOSE_ALL:
                    routes = this.viewTags.filter((item) => !item.affix);
                    path = "/";
                    break;
            }

            const names = routes.map((item) => item.name);
            const aliveTags = this.aliveTags.filter((item) => !names.includes(item));
            const viewTags: any[] = this.viewTags.filter((item) => !names.includes(item.name));

            this.$patch({ aliveTags, viewTags });

            await waiting(0);
            router.push(path);
        },
    },
});
